﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Web;
using System.Web.Mvc;
using ReportService.Common;
using ReportService.Models.ViewModels;

namespace ReportService.Models
{
    public class ReportServices
    {
        private IONReportModelDataContext _context = new IONReportModelDataContext();
        private IONReportConfigModelDataContext _configContext = new IONReportConfigModelDataContext();

        public ReportServices()
        {
            _context.CommandTimeout = 0; //Set no limit timeout
        }

        #region Load initialize data

        public IEnumerable<GetStoresByNameResult> GetListStore()
        {
            return _context.GetStoresByName().ToList();
        }

        public IEnumerable<GetDevicesResult> GetListDevice()
        {
            return _context.GetDevices().ToList();
        }

        public IEnumerable<GetListTimeOfUseResult> GetPriceBoard()
        {
            return _context.GetListTimeOfUse().ToList();
        }

        public IEnumerable<PL_TOU_TimeOfUse> GetListTOU()
        {
            return _configContext.PL_TOU_TimeOfUses.ToList();
        }

        public IEnumerable<GetReportYearResult> GetListReportYears()
        {
            return _context.GetReportYear().ToList();
        }

        public IEnumerable<SelectListItem> GetReportYears()
        {
            List<SelectListItem> lstYears = new List<SelectListItem>();

            if (ConfigurationManager.AppSettings.AllKeys.Contains("reportSinceYear"))
            {
                string sinceYear = ConfigurationManager.AppSettings["reportSinceYear"];
                for (int i = int.Parse(sinceYear); i <= DateTime.Now.Year; ++i)
                {
                    lstYears.Add(new SelectListItem { Text = i.ToString(), Value = i.ToString() });
                }
            }
            else
            {
                throw new Exception("Report year was not configured.");
            }

            return lstYears;
        }

        #endregion

        #region Price Board

        public void SavePriceBoard(string[] prices, string[] ids)
        {
            for (int i = 0; i < prices.Length; ++i)
            {
                string[] separateIDs = ids[i].Split('|');
                int touID = int.Parse(separateIDs[1]);
                PL_TOU_PriceBoard priceboard = _configContext.PL_TOU_PriceBoards.SingleOrDefault(p => p.StoreName == separateIDs[0] && p.TimeOfUse_ID == touID);
                if (priceboard != null)
                {
                    priceboard.Price = decimal.Parse(prices[i].Replace(",", ""));                    
                }
                else
                {
                    priceboard = new PL_TOU_PriceBoard();
                    priceboard.StoreName = separateIDs[0];
                    priceboard.TimeOfUse_ID = int.Parse(ids[1]);
                    _configContext.PL_TOU_PriceBoards.InsertOnSubmit(priceboard);
                }
            }
            _configContext.SubmitChanges();
        }

        #endregion

        #region Store Report Processing

        public IEnumerable<GetAED_DataOfStoreByPeriodResult> GetStoreReport(VMStoreReport viewModel)
        {
            DateTime fromDate = DateTime.ParseExact(viewModel.FromDate, "dd/MM/yyyy", null);
            DateTime toDate = DateTime.ParseExact(viewModel.ToDate, "dd/MM/yyyy", null);
            return _context.GetAED_DataOfStoreByPeriod(viewModel.StoreName, fromDate, toDate);
        }

        public string GenerateStoreReportHTML(IEnumerable<GetAED_DataOfStoreByPeriodResult> reportData,
                                              IEnumerable<PL_TOU_TimeOfUse> listTOU,
                                              VMStoreReport viewModel)
        {
            StringBuilder sbHTML = new StringBuilder();

            IEnumerable<PL_TOU_PriceBoard> ListPriceOfStore = (from pb in _configContext.PL_TOU_PriceBoards where pb.StoreName == viewModel.StoreName select pb);
            IEnumerable<string> ListDevices = (from rd in reportData select rd.SourceName).Distinct().OrderBy(p => p);

            DateTime fromDate = DateTime.ParseExact(viewModel.FromDate, "dd/MM/yyyy", null);
            DateTime toDate = DateTime.ParseExact(viewModel.ToDate, "dd/MM/yyyy", null);
            for (int i = fromDate.Month; i <= toDate.Month; i++)
            {
                //Generate MONTH header here
                sbHTML.Append(GenerateMONTHDisplayLine(i));
                sbHTML.Append(GenerateHTMLEmptyLine());
                sbHTML.Append(GenerateHTMLDayHeaderLine());
                sbHTML.Append(GenerateHTMLTitleHeaderLine());

                foreach (string device in ListDevices.Where(p => !(viewModel.ListExceptDevicesOfStore ?? "").Contains("|" + p + "|")))
                {
                    sbHTML.Append("<tr height='19' style='height:14.25pt'>");
                    sbHTML.Append("<td height='19' class=reportVerticalBorderCell style='height:14.25pt'>&nbsp;</td>");
                    sbHTML.Append("<td class='normalEmptyCell'></td>");
                    sbHTML.Append("<td class='reportDeviceHeadCell' style='border-top:none'>" + device + "</td>");
                    for (int col = 1; col <= 64; ++col)
                    {
                        sbHTML.Append("<td class='reportDeviceHeadCell' style='border-top:none;border-left:none'>&nbsp;</td>");
                    }
                    sbHTML.Append("</tr>");

                    foreach (PL_TOU_TimeOfUse tou in listTOU)
                    {
                        sbHTML.Append("<tr height='19' style='height:14.25pt'>");
                        sbHTML.Append("<td height='19' class=reportVerticalBorderCell style='height:14.25pt'>&nbsp;</td>");
                        sbHTML.Append("<td class='normalEmptyCell'></td>");
                        sbHTML.Append("<td class='reportTOUHeadCell' style='border-top:none'>" + tou.TimeOfUse_Name + "</td>");

                        double sumMonth = 0;
                        double sumMonthCost = 0;
                        DateTime runDate = new DateTime(fromDate.Year, i, 1);
                        for (int day = 1; day <= 31; ++day)
                        {
                            if (runDate.Month == i)
                            {
                                string compareDate = runDate.ToString("dd/MM/yyyy");
                                GetAED_DataOfStoreByPeriodResult obj = reportData.SingleOrDefault(p => p.DateUTC == compareDate && p.SourceName == device && p.Peek_Of_Time == tou.TimeOfUse_ID);

                                if (obj != null)
                                {
                                    PL_TOU_PriceBoard price = ListPriceOfStore.SingleOrDefault(p => p.TimeOfUse_ID == tou.TimeOfUse_ID);
                                    double data = Math.Round(obj.DataValue ?? 0);
                                    double cost = price != null ? Math.Round(data * (double)price.Price) : 0;
                                    sbHTML.Append("<td class='reportDataCell' style='border-top:none;border-left:none'>" + data.ToString("#,#0") + "</td>");
                                    sbHTML.Append("<td class='reportDataCell' style='border-top:none;border-left:none'>" + cost.ToString("#,#0") + "</td>");
                                    sumMonth += data;
                                    sumMonthCost += cost;
                                }
                                else
                                {
                                    sbHTML.Append("<td class='reportDataCell' style='border-top:none;border-left:none'>&nbsp;</td>");
                                    sbHTML.Append("<td class='reportDataCell' style='border-top:none;border-left:none'>&nbsp;</td>");
                                }
                            }
                            else
                            {
                                sbHTML.Append("<td class='reportDataCell' style='border-top:none;border-left:none'>&nbsp;</td>");
                                sbHTML.Append("<td class='reportDataCell' style='border-top:none;border-left:none'>&nbsp;</td>");
                            }

                            runDate = runDate.AddDays(1);
                        }

                        sbHTML.Append("<td class='reportDataCell' style='border-top:none;border-left:none'>" + sumMonth.ToString("#,#0") + "</td>");
                        sbHTML.Append("<td class='reportDataCell' style='border-top:none;border-left:none'>" + sumMonthCost.ToString("#,#0") + "</td>");
                    }
                }

                sbHTML.Append(GenerateHTMLEmptyFooterLine1());
                sbHTML.Append(GenerateHTMLEmptyFooterLine2());
                sbHTML.Append(GenerateHTMLEmptyLine());
            }

            return sbHTML.ToString();
        }

        //public string CreateXSLWrapper()
        //{
        //    StringBuilder sbXSL = new StringBuilder();
        //    sbXSL.Append("<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">");
        //    sbXSL.Append("<xsl:template match=\"/\">");
        //    sbXSL.Append("<HTML><HEAD></HEAD><BODY>{0}</BODY></HTML>");
        //    sbXSL.Append("</xsl:template");
        //    sbXSL.Append("</xsl:stylesheet>");
        //    return sbXSL.ToString();
        //}

        private string GenerateMONTHDisplayLine(int month)
        {
            StringBuilder sbHTML = new StringBuilder();

            sbHTML.Append("<tr height='28' style='height:21.0pt'>");
            sbHTML.Append("<td height='28' class=reportVerticalBorderCell style='height:21.0pt'>&nbsp;</td>");
            sbHTML.Append("<td class='normalEmptyCell'></td>");
            sbHTML.Append("<td class='reportMonthHeader'>" + ReportUtils.MonthShortText[month] + "</td>");
            for (int i = 0; i < 64; ++i)
            {
                sbHTML.Append("<td class='normalEmptyCell'></td>");
            }
            sbHTML.Append("</tr>");

            return sbHTML.ToString();
        }

        private string GenerateHTMLEmptyLine()
        {
            StringBuilder sbHTML = new StringBuilder();

            sbHTML.Append("<tr height='19' style='height:14.25pt'>");
            sbHTML.Append("<td height='19' class=reportVerticalBorderCell style='height:14.25pt'>&nbsp;</td>");
            for (int i = 0; i < 66; ++i)
            {
                sbHTML.Append("<td class='normalEmptyCell'></td>");
            }
            sbHTML.Append("</tr>");

            return sbHTML.ToString();
        }

        private string GenerateHTMLEmptyFooterLine1()
        {
            StringBuilder sbHTML = new StringBuilder();

            sbHTML.Append("<tr height='19' style='height:14.25pt'>");
            sbHTML.Append("<td height='19' class=reportVerticalBorderCell style='height:14.25pt'>&nbsp;</td>");
            sbHTML.Append("<td class='normalEmptyCell'></td>");
            sbHTML.Append("<td class='reportDataCell' style='border-top:none'>&nbsp;</td>");
            for (int i = 0; i < 64; ++i)
            {
                sbHTML.Append("<td class='reportDataCell' style='border-top:none;border-left:none'>&nbsp;</td>");
            }
            sbHTML.Append("</tr>");

            return sbHTML.ToString();
        }

        private string GenerateHTMLEmptyFooterLine2()
        {
            StringBuilder sbHTML = new StringBuilder();

            sbHTML.Append("<tr height='19' style='height:14.25pt'>");
            sbHTML.Append("<td height='19' class=reportVerticalBorderCell style='height:14.25pt'>&nbsp;</td>");
            sbHTML.Append("<td class='normalEmptyCell'></td>");
            sbHTML.Append("<td class='reportDataFooterCell' style='border-top:none'>&nbsp;</td>");
            for (int i = 0; i < 64; ++i)
            {
                sbHTML.Append("<td class='reportDataFooterCell' style='border-top:none;border-left:none'>&nbsp;</td>");
            }
            sbHTML.Append("</tr>");

            return sbHTML.ToString();
        }

        private string GenerateHTMLDayHeaderLine()
        {
            StringBuilder sbHTML = new StringBuilder();

            sbHTML.Append("<tr height='19' style='height:14.25pt'>");
            sbHTML.Append("<td height='19' class=reportVerticalBorderCell style='height:14.25pt'>&nbsp;</td>");
            sbHTML.Append("<td class='normalEmptyCell'></td>");
            sbHTML.Append("<td rowspan=2 class=\"reportDayHeader\">&nbsp;</td>");
            for (int i = 1; i <= 31; ++i)
            {
                sbHTML.Append("<td colspan='2' class=\"reportDayHeader\" style='border-left:none'>" + i.ToString() + "</td>");
            }
            sbHTML.Append("<td colspan='2' class=\"reportDayHeader\" style='border-left:none'>Monthly</td>");
            sbHTML.Append("</tr>");

            return sbHTML.ToString();
        }

        private string GenerateHTMLTitleHeaderLine()
        {
            StringBuilder sbHTML = new StringBuilder();

            sbHTML.Append("<tr height='51' style='height:38.25pt'>");
            sbHTML.Append("<td height='51' class=reportVerticalBorderCell style='height:38.25pt'>&nbsp;</td>");
            sbHTML.Append("<td class='normalEmptyCell'></td>");
            for (int i = 1; i <= 32; ++i)
            {
                sbHTML.Append("<td class='reportHeaderTextCell' width=110 style='border-top:none;border-left:none;width:83pt'>Daily energy consumption (kWh)</td>");
                sbHTML.Append("<td class='reportHeaderTextCell' width=110 style='border-top:none;border-left:none;width:83pt'>Energy cost (VND)</td>");
            }
            sbHTML.Append("</tr>");

            return sbHTML.ToString();
        } 
        #endregion

        #region Summary Report Processing

        public IEnumerable<GetAED_SummaryDataOfStoreByYearResult> GetStoreSummaryReport(string sYear)
        {
            return _context.GetAED_SummaryDataOfStoreByYear(sYear);
        }

        public string GenerateSummaryReportHTML(IEnumerable<GetAED_SummaryDataOfStoreByYearResult> reportData, string listOfExceptStore)
        {
            StringBuilder sbHTML = new StringBuilder();
                       


            return sbHTML.ToString();
        }
        #endregion
    }
}